package controllers;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import models.Entity;
import models.Sexo;
import models.TipoDocumento;
import models.users.Role;
import models.users.User;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Row;
import org.codehaus.jackson.JsonNode;

import play.db.jpa.Transactional;
import play.libs.Crypto;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Http.MultipartFormData;
import play.mvc.Http.MultipartFormData.FilePart;
import play.mvc.Result;
import services.DAO;
import services.PasswordHash;
import vos.LoginCredentials;

public class UserCtrl extends Controller {

	public static final String USER_ID_KEY = "userId";
	public static final String ROLE_KEY = "role";
	public static final String ACTOR_ID_KEY = "actorId";

	@Transactional
	public static Result main() {
		System.out.println(request().getClass());
		String roleName = session(ROLE_KEY);
		if (roleName != null)
			try {

				Role r = Role.valueOf(roleName);
				return ok(new File(r.getRedirectURL()));
			} catch (IllegalArgumentException e) {

				return ok(new File("public/authentication/authentication.html"));
			}
		else {

			return ok(new File("public/authentication/authentication.html"));
		}

	}

	@Transactional(readOnly = true)
	public static Result login() throws NoSuchAlgorithmException,
			InvalidKeySpecException {
		LoginCredentials c = Json.fromJson(request().body().asJson(),
				LoginCredentials.class);
		List<User> res = DAO.query(User.class, -1, "username", c.username,
				"role", c.role);

		if (res.isEmpty()
				|| !PasswordHash.validatePassword(c.password, res.get(0)
						.getPassword()))
			return unauthorized("Usuario o contraseña incorrectos");

		User user = res.get(0);
		Role role = user.getRole();
		session(USER_ID_KEY, user.getId().toString());
		if (user.getIdActor() != null)
			session(ACTOR_ID_KEY, user.getIdActor().toString());
		session(ROLE_KEY, role.name());

		if (role.getEntity() != null) {
			Entity<?> e = DAO.find(role.getEntity(), user.getIdActor());
			JsonNode node = Json.toJson(e);
			Iterator<Entry<String, JsonNode>> iter = node.getFields();

			while (iter.hasNext()) {

				Entry<String, JsonNode> entry = iter.next();

				session(entry.getKey(), entry.getValue().asText());
			}
		}
		if (c.rememberMe) {
			// FIXME
			response().setCookie("remember", Crypto.sign(c.username));
			response().setCookie("username", c.username);
		}
		return ok();
	}

	@Transactional(readOnly = true)
	public static Result getMyInfo() {
		Long userId = Long.parseLong(session(USER_ID_KEY));
		User u = DAO.find(User.class, userId);
		return ok(Json.toJson(u));
	}

	public static Result logout() {
		session().clear();
		return ok();
	}

	@Transactional(readOnly = true)
	public static Result getJornadas() {
		return ok(Json.toJson(DAO.execute("SELECT j FROM Jornada j", -1)));
	}

	@Transactional(readOnly = true)
	public static Result getMaterias() {
		return ok(Json.toJson(DAO.execute("SELECT j FROM Materia j", -1)));
	}

	@Transactional(readOnly = true)
	public static Result getGrados() {
		return ok(Json.toJson(DAO.execute("SELECT j FROM Grado j", -1)));
	}

	public static Result getTiposDocumento() {
		return ok(Json.toJson(TipoDocumento.values()));
	}

	public static Result getSexos() {
		return ok(Json.toJson(Sexo.values()));
	}

	public static Result uploadFile() throws FileNotFoundException, IOException {
		MultipartFormData body = request().body().asMultipartFormData();
		FilePart fp = body.getFile("file");
		File f = fp.getFile();
		POIFSFileSystem pfs = new POIFSFileSystem(new FileInputStream(f));
		HSSFWorkbook wb = new HSSFWorkbook(pfs);
		HSSFSheet sheet = wb.getSheetAt(0);
		Iterator<Row> it = sheet.iterator();
		while (it.hasNext()) {
			Row r = it.next();

		}
		return ok();
	}
}
